package com.un.ebs.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.sys.domain.Function;
import com.un.ebs.sys.domain.FunctionTable;
import com.un.ebs.sys.dto.FunctionUpdateDto;
import com.un.ebs.sys.dto.FunctionVo;
import com.un.ebs.sys.mapper.FunctionMapper;
import com.un.ebs.sys.mapper.FunctionTableMapper;
import com.un.ebs.sys.mapper.TableMapper;
import com.un.ebs.sys.service.FunctionService;
import com.un.ebs.sys.service.ScriptService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class FunctionServiceImpl extends ServiceImpl<FunctionMapper, Function> implements FunctionService {

    @Autowired
    ScriptService scriptService;

    @Resource
    private FunctionMapper functionMapper;

    @Resource
    private FunctionTableMapper functionTableMapper;

    @Resource
    private TableMapper tableMapper;

    @Override
    public String save(FunctionUpdateDto req) {
        Function function = functionMapper.selectById(req.getId());
        if (function == null) {
            function = new Function();

            LambdaQueryWrapper<Function> lq = Wrappers.lambdaQuery();
            lq.eq(Function::getFunName, req.getFunName());
            Optional<Function> maxVersion = baseMapper.selectList(lq).stream().max(Comparator.comparing(Function::getVersionNo));
            if (maxVersion.isPresent()) {
                function.setVersionNo(maxVersion.get().getVersionNo() + 1);
            } else {
                function.setVersionNo(1);
            }
        } else {
//            if (!function.getCreateAt().equals(SecurityUtils.getUserContent().getId())) {
//                throw new BusinessException("你不是当前函数的创建人，不可以修改。");
//            }
            if (function.getReleaseStatus()) {
                throw new BusinessException("已发布的函数不可以修改。");
            }
        }

        function.setFunName(req.getFunName());
        function.setRemark(req.getRemark());
        function.setTagName(req.getTagName());
        function.setReleaseStatus(false);
        function.setFunContext(req.getFunContext());
        function.insertOrUpdate();


        if (!StringUtils.isNullOrEmpty(req.getTableIds())) {
            for (String id : req.getTableIds()) {
                LambdaQueryWrapper<FunctionTable> query = Wrappers.lambdaQuery();
                query.eq(FunctionTable::getFunId, function.getId());
                query.eq(FunctionTable::getTableId, id);
                if (functionTableMapper.selectCount(query) >= 1) {
                    continue;
                }
                FunctionTable item = new FunctionTable();
                item.setFunId(function.getId());
                item.setTableId(id);
                item.insertOrUpdate();
            }
        }

        return function.getId();
    }

    @Override
    public Function updateFunContext(String id, String context) {
        Function function = baseMapper.selectById(id);
        if (function == null) {
            throw new BusinessEntityNotFoundException(id, "函数");
        }
        if (function.getReleaseStatus()) {
            throw new BusinessException("已发布的函数不可以修改。");
        }

        FunctionUpdateDto req = new FunctionUpdateDto();
        req.setFunName(function.getFunName());
        req.setTagName(function.getTagName());
        req.setFunContext(context);
        req.setRemark(function.getRemark());
        String newId = save(req);
        return baseMapper.selectById(newId);

    }

    @Override
    public void delete(String id) {
        baseMapper.deleteById(id);
    }

    @Override
    public void deleteTable(String funId, String tableId) {
        Function function = baseMapper.selectById(funId);
        if (function == null) {
            return;
        }
        if (function.getReleaseStatus()) {
            throw new BusinessException("已发布的函数不可以修改。");
        }

        LambdaQueryWrapper<FunctionTable> lq = Wrappers.lambdaQuery();
        lq.eq(FunctionTable::getFunId, funId);
        lq.eq(FunctionTable::getTableId, tableId);
        functionTableMapper.delete(lq);
    }

    @Override
    public void renameTag(String oldName, String newName) {
        LambdaQueryWrapper<Function> lq = Wrappers.lambdaQuery();
        //lq.eq(Function::getCreateAt, SecurityUtils.getUserContent().getId());
        lq.eq(Function::getTagName, oldName);
        for (Function function : baseMapper.selectList(lq)) {
            function.setTagName(newName);
            function.updateById();
        }
    }

    @Override
    public void release(String id, String remark) {
        Function function = baseMapper.selectById(id);
        if (function == null) {
            throw new BusinessEntityNotFoundException(id, "函数");
        }

        function.setReleaseStatus(true);
        function.setReleaseTime(new Date());
        function.setRemark(remark);
        function.updateById();
        scriptService.add(function.getFunName(), function.getFunContext());
    }

    @Override
    public void releaseCancel(String id) {
        Function function = baseMapper.selectById(id);
        if (function == null) {
            throw new BusinessEntityNotFoundException(id, "函数");
        }
        if (!function.getReleaseStatus()) {
            return;
        }

        function.setReleaseStatus(false);
        function.setReleaseTime(null);
        function.updateById();

        scriptService.del(function.getFunName());
    }

    @Override
    public FunctionVo queryViewById(String id) {
        Function function = baseMapper.selectById(id);
        if (function == null) {
            throw new BusinessEntityNotFoundException(id, "函数");
        }
        FunctionVo ret = new FunctionVo();
        BeanUtils.copyProperties(function, ret);
        LambdaQueryWrapper<FunctionTable> lq = Wrappers.lambdaQuery();
        lq.eq(FunctionTable::getFunId, id);
        ret.setTables(tableMapper.selectBatchIds(functionTableMapper.selectList(lq).stream().map(s -> s.getTableId()).collect(Collectors.toList())));
        return ret;
    }

    @Override
    public IPage<Function> query(String searchText, String tagName, int pageSize, int pageIndex) {
        IPage<Function> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<Function> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(tagName)) {
            lq.eq(Function::getTagName, tagName);
        }
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(Function::getFunName, searchText.trim());
        }
        return baseMapper.selectPage(page, lq);
    }

    @Override
    public List<Function> queryReleases(String tagName) {
        LambdaQueryWrapper<Function> lq = Wrappers.lambdaQuery();
        lq.eq(Function::getReleaseStatus, true);
        if (!StringUtils.isNullOrEmpty(tagName)) {
            lq.eq(Function::getTagName, tagName);
        }
        return baseMapper.selectList(lq);
    }

    @Override
    public List<Function> queryHistory(String funName) {
        LambdaQueryWrapper<Function> lq = Wrappers.lambdaQuery();
        lq.eq(Function::getFunName, funName);
        lq.orderByDesc(Function::getVersionNo);
        return baseMapper.selectList(lq);
    }

    @Override
    public List<String> queryTags() {
        return baseMapper.selectTagNames();
    }
}
